﻿using Commons.ReturnData;
using IdentityServer.Domain.Entities;
using IdentityServer.Domain.IRepositories;
using IdentityServer.Domain.IServices;
using IdentityServer.Infrastructure.Options;
using JWT;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Diagnostics;
using System.Security.Claims;
using System.Text.Json;

namespace IdentityServer.Infrastructure.Services
{
    public class IdDomainService
    {
        private readonly IIdRepository repository;
        private readonly ITokenService tokenService;
        private readonly IOptions<JWTOptions> optJWT;
        private readonly IEmailClient qqEmailClient;
        private readonly IWeChatRepository weChatRepository;

        public IdDomainService(IIdRepository repository,
             ITokenService tokenService, IOptions<JWTOptions> optJWT, IEmailClient qqEmailClient, IWeChatRepository weChatRepository)
        {
            this.repository = repository;
            this.tokenService = tokenService;
            this.optJWT = optJWT;
            this.qqEmailClient = qqEmailClient;
            this.weChatRepository = weChatRepository;
        }

        private async Task<SignInResult> CheckUserNameAndPwdAsync(string userName, string password)
        {
            var user = await repository.FindByNameAsync(userName);
            if (user == null)
            {
                return SignInResult.Failed;
            }
            //CheckPasswordSignInAsync会对于多次重复失败进行账号禁用
            var result = await repository.CheckForSignInAsync(user, password, true);
            return result;
        }
        private async Task<SignInResult> CheckPhoneNumAndPwdAsync(string phoneNum, string password)
        {
            var user = await repository.FindByPhoneNumberAsync(phoneNum);
            if (user == null)
            {
                return SignInResult.Failed;
            }
            var result = await repository.CheckForSignInAsync(user, password, true);
            return result;
        }
        private async Task<SignInResult> CheckEmailAndPwdAsync(string email, string password)
        {
            var user = await repository.FindByEmailAsync(email);
            if (user == null)
            {
                return SignInResult.Failed;
            }
            var result = await repository.CheckForSignInAsync(user, password, true);
            return result;
        }

        //<(SignInResult Result, string? Token)>  元组的语法
        public async Task<(SignInResult Result, string? Token)> LoginByPhoneAndPwdAsync(string phoneNum, string password)
        {
            var checkResult = await CheckPhoneNumAndPwdAsync(phoneNum, password);
            if (checkResult.Succeeded)
            {
                var user = await repository.FindByPhoneNumberAsync(phoneNum);
                string token = await BuildTokenAsync(user);
                return (SignInResult.Success, token);
            }
            else
            {
                return (checkResult, null);
            }
        }

        public async Task<(SignInResult Result, string? Token)> LoginByUserNameAndPwdAsync(string userName, string password)
        {
            var checkResult = await CheckUserNameAndPwdAsync(userName, password);
            if (checkResult.Succeeded)
            {
                var user = await repository.FindByNameAsync(userName);
                string token = await BuildTokenAsync(user);
                return (SignInResult.Success, token);
            }
            else
            {
                return (checkResult, null);
            }
        }
        public async Task<(SignInResult Result, string? Token)> LoginByEmailAndPwdAsync(string email, string password)
        {
            var checkResult = await CheckEmailAndPwdAsync(email, password);
            if (checkResult.Succeeded)
            {
                var user = await repository.FindByEmailAsync(email);
                string token = await BuildTokenAsync(user);
                return (SignInResult.Success, token);
            }
            else
            {
                return (checkResult, null);
            }
        }


        public async Task<SingleResult> CreateByEmailAsync(string userName,string email,string password)
        {
            var user = new AppUser(userName);
            user.Email= email;
            user.EmailConfirmed = true;
            var cUser = await repository.CreateAsync(user, password);
            Debug.Assert(cUser.Succeeded);
            var r = await repository.AddToRoleAsync(user,"user");
            Debug.Assert(r.Succeeded);
            return new SingleResult(true);
        }

        private async Task<string> BuildTokenAsync(AppUser user)
        {
            var roles = await repository.GetRolesAsync(user);
            List<Claim> claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()));
            foreach (string role in roles)
            {
                claims.Add(new Claim(ClaimTypes.Role, role));
            }
            return tokenService.BuildToken(claims, optJWT.Value);
        }
        public async Task<MessageResult> EmailSendAsync(string email)
        {
            Random rd = new Random();
            var code = rd.Next(100000, 999999).ToString();
            var user = await repository.FindByEmailAsync(email);
            if(user != null)
            {
                return new MessageResult(404, "该邮箱已经注册！", false);
            }
            var res = await qqEmailClient.SendEmail(email, code, "请查收您的验证码", "您的验证码是：" + code);
            if (res)
            {
                return new MessageResult("邮件已发送！");
            }
            else
            {
                return new MessageResult(404, "发送出错！", false);
            }
        }

        public async Task<LoginResult> loginByWeChatOpenIdAsync(string code)
        {
            string authUrl = "https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code";
            //这里通过环境变量获取Id和密钥，你也可以改成明文
            string appId = Environment.GetEnvironmentVariable("AppID");
            string appSecret = Environment.GetEnvironmentVariable("AppSecret");
            //最后的url拼接
            authUrl = authUrl + "&appid=" + appId + "&secret=" + appSecret + "&js_code=" + code;
            var httpClient = new HttpClient();
            //发起get请求
            using HttpResponseMessage response = await httpClient.GetAsync(authUrl);
            var jsonString = await response.Content.ReadAsStringAsync();
            //反序列化成对象
            WechatOptions? wechatOptions = JsonSerializer.Deserialize<WechatOptions>(jsonString);
            //没获取到openid就登录失败了
            if(wechatOptions.openid != null)
            {
                var user = new AppUser();
                var token = "";
                //查找数据库里有没有这个openid
                var chetWeChat = await weChatRepository.FindByOpenIdAsync(wechatOptions.openid);
                if(chetWeChat != null)
                {
                    //有的话通过userid查找这个用户
                    user = await repository.FindByIdAsync(chetWeChat.AppUserId);
                    
                }
                else
                {
                    //创建用户需要userName和password，为了不重复我就通过时间戳了
                    TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                    var pwd  = Convert.ToInt64(ts.TotalSeconds).ToString();
                    user.UserName = "ChatGPT_" + pwd;
                    await repository.CreateAsync(user, pwd);
                    user = await repository.FindByNameAsync(user.UserName);
                    //用新建的用户id和openid添加一条数据
                    var newUser = new WeChatUser(user.Id, wechatOptions.openid);
                    var res = await weChatRepository.CreateWechatUserAsync(newUser);
                }
                //获取token
                token = await BuildTokenAsync(user);
                return new LoginResult(token);

            }
            return new LoginResult(401,"登录失败");
        }
    }
}
